#include "coding.h"
#include "../util.h"

/* Activision / EXAKT Entertainment's DPCM for Supercar Street Challenge */

#if 0
To build table:

int32_t bring_round(int32_t v) {  
    return v | (v >> 12);
}   

for (i=0x00;i<0x20;i++) 
    sassc_steps[i] = bring_round(i<<4);    
for (i=0x20;i<0x40;i++)   
    sassc_steps[i] = bring_round(((i-0x20)*7+0x20)<<4);
for (i=0x40;i<0x60;i++)
    sassc_steps[i] = bring_round(((i-0x40)*24+0x100)<<4);
for (i=0x60;i<0x80;i++)
    sassc_steps[i] = bring_round(((i-0x60)*96+0x400)<<4);

for (i=0x80;i<0xFF;i++)
    sassc_steps[i] = -sassc_steps[i-0x80];

sassc_steps[0xFF] = sassc_steps[0x7F];
#endif

static const int32_t sassc_steps[256] = {
       0,      16,      32,      48,      64,      80,      96,     112,
     128,     144,     160,     176,     192,     208,     224,     240,
     256,     272,     288,     304,     320,     336,     352,     368,
     384,     400,     416,     432,     448,     464,     480,     496,
     512,     624,     736,     848,     960,    1072,    1184,    1296,
    1408,    1520,    1632,    1744,    1856,    1968,    2080,    2192,
    2304,    2416,    2528,    2640,    2752,    2864,    2976,    3088,
    3200,    3312,    3424,    3536,    3648,    3760,    3872,    3984,
    4097,    4481,    4865,    5249,    5633,    6017,    6401,    6785,
    7169,    7553,    7937,    8322,    8706,    9090,    9474,    9858,
   10242,   10626,   11010,   11394,   11778,   12162,   12547,   12931,
   13315,   13699,   14083,   14467,   14851,   15235,   15619,   16003,
   16388,   17924,   19460,   20997,   22533,   24069,   25606,   27142,
   28679,   30215,   31751,   33288,   34824,   36360,   37897,   39433,
   40970,   42506,   44042,   45579,   47115,   48651,   50188,   51724,
   53261,   54797,   56333,   57870,   59406,   60942,   62479,   64015,

       0,     -16,     -32,     -48,     -64,     -80,     -96,    -112,
    -128,    -144,    -160,    -176,    -192,    -208,    -224,    -240,
    -256,    -272,    -288,    -304,    -320,    -336,    -352,    -368,
    -384,    -400,    -416,    -432,    -448,    -464,    -480,    -496,
    -512,    -624,    -736,    -848,    -960,   -1072,   -1184,   -1296,
   -1408,   -1520,   -1632,   -1744,   -1856,   -1968,   -2080,   -2192,
   -2304,   -2416,   -2528,   -2640,   -2752,   -2864,   -2976,   -3088,
   -3200,   -3312,   -3424,   -3536,   -3648,   -3760,   -3872,   -3984,
   -4097,   -4481,   -4865,   -5249,   -5633,   -6017,   -6401,   -6785,
   -7169,   -7553,   -7937,   -8322,   -8706,   -9090,   -9474,   -9858,
  -10242,  -10626,  -11010,  -11394,  -11778,  -12162,  -12547,  -12931,
  -13315,  -13699,  -14083,  -14467,  -14851,  -15235,  -15619,  -16003,
  -16388,  -17924,  -19460,  -20997,  -22533,  -24069,  -25606,  -27142,
  -28679,  -30215,  -31751,  -33288,  -34824,  -36360,  -37897,  -39433,
  -40970,  -42506,  -44042,  -45579,  -47115,  -48651,  -50188,  -51724,
  -53261,  -54797,  -56333,  -57870,  -59406,  -60942,  -62479,   64015,
};

void decode_sassc(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) {
    int i;
    int32_t sample_count;
    int32_t hist = stream->adpcm_history1_32;

    for (i = first_sample, sample_count = 0; i < first_sample + samples_to_do; i++, sample_count += channelspacing) {
        uint8_t index = read_u8(stream->offset + i, stream->streamfile);
        hist = hist + sassc_steps[index];
        outbuf[sample_count] = clamp16(hist);
    }

    stream->adpcm_history1_32 = hist;
}
